package vip.web3.api.service.impl.biz;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import vip.web3.admin.job.task.ApiBaseTask;
import vip.web3.admin.sys.dao.biz.AOrderDao;
import vip.web3.admin.sys.entity.biz.AOrderEntity;
import vip.web3.admin.sys.redis.RedisConstant;
import vip.web3.admin.sys.service.biz.IAUserService;
import vip.web3.admin.sys.service.sys.SysConfigService;
import vip.web3.api.dao.biz.*;
import vip.web3.api.entity.biz.*;
import vip.web3.api.form.user.OrderForm;
import vip.web3.api.form.user.RecordForm;
import vip.web3.api.service.biz.OrderService;
import vip.web3.api.service.biz.UserService;
import vip.web3.api.utils.Arith;
import vip.web3.api.vo.biz.RecordVo;
import vip.web3.common.enums.ActiveEnum;
import vip.web3.common.enums.OperateEnum;
import vip.web3.common.enums.StatusEnum;
import vip.web3.common.enums.WalletTypeEnum;
import vip.web3.common.enums.user.TeamLevelEnum;
import vip.web3.common.exception.RRException;
import vip.web3.common.utils.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Autowired
    private ProductDao productDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private UserWalletDao userWalletDao;

    @Autowired
    private RecordDao recordDao;

    @Resource
    private SysConfigService sysConfigService;
    @Resource
    private OrderDao orderDao;
    @Resource
    private IAUserService userService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void order(OrderForm form) {
        //会员等级及分红制度
        UserEntity user = this.userDao.selectById(Servlets.getUserId());
        UserWalletEntity wallet = this.userWalletDao
                .selectOne(Wrappers.<UserWalletEntity>lambdaQuery().eq(UserWalletEntity::getUserId, Servlets.getUserId()));

        if (Objects.isNull(user) || Objects.isNull(wallet)) {
            throw new RRException("用户不存在!", -1);
        }


        // 如果二次下单要用原来的钱包type
        WalletTypeEnum buyType = WalletTypeEnum.get(form.getPayType());
        WalletTypeEnum walletType = WalletTypeEnum.get(wallet.getType());
        if (WalletTypeEnum.CNY.equals(walletType) && !WalletTypeEnum.CNY.equals(buyType)) {
            throw new RRException("您只能使用人民币购买!", -1);
        }

        if (WalletTypeEnum.USDT.equals(walletType) && !WalletTypeEnum.USDT.equals(buyType)) {
            throw new RRException("您只能使用USDT购买!", -1);
        }

        ProductEntity product = this.productDao.selectById(form.getProductId());
        if (Objects.isNull(product)) {
            throw new RRException("产品不存在!", -1);
        }

        if (StatusEnum.OFF.equals(StatusEnum.getEnum(product.getStatus()))) {
            throw new RRException("产品错误!", -1);
        }

        if (Objects.isNull(product.getActive())) {
            throw new RRException("产品最大下单量错误!", -1);
        }

        Integer counted = this.lambdaQuery()
                .eq(OrderEntity::getUserId, Servlets.getUserId())
                .eq(OrderEntity::getProId, form.getProductId())
                .count();

        if (Objects.nonNull(counted) && counted >= product.getActive()) {
            throw new RRException("每份产品只能买3份!", -1);
        }

        // 要激活自己用户状态
        if (ActiveEnum.NO_ACTIVE.equals(ActiveEnum.get(user.getActive()))) {
            UserEntity userEntity = new UserEntity();
            userEntity.setId(Servlets.getUserId());
            userEntity.setActive(ActiveEnum.ACTIVE.getCode());
            String format = DateUtils.format(new Date(), DateUtils.DATE_PATTERN);
            try {
                Date parse = DateUtils.parse(format + " 00:00:00", DateUtils.DATE_TIME_PATTERN);
                userEntity.setActiveStart(parse);
                userEntity.setActiveTeamBegin(parse);
                userEntity.setActiveEnd(DateUtils.addDateDays(parse, 30));
                userEntity.setActiveTeamEnd(DateUtils.addDateDays(parse, 30));
            } catch (Exception exception) {
            }
            int updated = this.userDao.updateById(userEntity);
            if (updated < 1) {
                throw new RRException("下单失败,稍后再试!", -1);
            }
        }

        UserWalletEntity userWalletEntity = new UserWalletEntity();
        userWalletEntity.setId(wallet.getId());
        userWalletEntity.setVersion(wallet.getVersion());
        // 改余额表余额，第一次下单给自己钱包定type
        if (WalletTypeEnum.CNY.equals(buyType)) {
            // 余额不够要先充值
            if (wallet.getAmountCny().compareTo(product.getPriceCny()) < 0) {
                throw new RRException("人民币不足请先充值!", -1);
            }
            userWalletEntity.setAmountCny(product.getPriceCny());
            if (WalletTypeEnum.UNKNOWN.equals(walletType)) {
                userWalletEntity.setType(WalletTypeEnum.CNY.getCode());
            }
            userWalletEntity.setType(WalletTypeEnum.CNY.getCode());
        }

        if (WalletTypeEnum.USDT.equals(buyType)) {
            // 余额不够要先充值
            if (wallet.getAmountUsdt().compareTo(product.getPriceUsdt()) < 0) {
                throw new RRException("usdt不足请先充值!", -1);
            }
            userWalletEntity.setAmountUsdt(product.getPriceUsdt());
            if (WalletTypeEnum.UNKNOWN.equals(walletType)) {
                userWalletEntity.setType(WalletTypeEnum.USDT.getCode());
            }
            userWalletEntity.setType(WalletTypeEnum.USDT.getCode());
        }


        int u = this.userWalletDao.buyProductUpdateAmount(userWalletEntity, buyType);
        if (u < 1) {
            throw new RRException("下单失败,稍后再试!", -1);
        }

        // 首次购买1-8任何一款产品都送0号产品，投资累计收益累计，复购不送
        Integer count = this.lambdaQuery().eq(OrderEntity::getUserId, Servlets.getUserId()).count();
        if (Objects.isNull(count) || count < 1) {
            ProductEntity freeProduct = this.productDao
                    .selectOne(Wrappers.<ProductEntity>lambdaQuery().eq(ProductEntity::getId, StatusEnum.OPEN.getCode()));
            int inserted = this.baseMapper.insert(this.createOrder(form, user, freeProduct));
            if (inserted < 1) {
                throw new RRException("下单失败,稍后再试!", -1);
            }
        }
        // 记录order表
        int inserted = this.baseMapper.insert(this.createOrder(form, user, product));
        if (inserted < 1) {
            throw new RRException("下单失败,稍后再试!", -1);
        }
        RecordEntity entity = this.createRecord(form, user, product);
        int insert = this.recordDao.insert(entity);
        if (insert < 1) {
            throw new RRException("下单失败,稍后再试!", -1);
        }

        /**
         * 根据条件修改会员等级
         */
        //必须是激活用户
        if (ActiveEnum.ACTIVE.equals(ActiveEnum.get(user.getActive()))) {
            handleTeamLevel(user);
            userService.quarterReward(user.getId());
        }
    }

    /**
     * 处理会员团队等级
     */
    private void handleTeamLevel(UserEntity user) {
        //更新开始日期和结束日期
        Date startDate = null == user.getActiveStart() ? new Date() : user.getActiveStart();
        Integer day = DateUtils.diffDate(new Date(), startDate);
        Integer index = (int) Math.ceil(day / 30);
        user.setActiveTeamBegin(DateUtils.addDateDays(user.getCreateTime(), (index - 1) * 30));
        user.setActiveTeamEnd(DateUtils.addDateDays(user.getCreateTime(), index * 30));

        LambdaQueryWrapper<OrderEntity> query = new LambdaQueryWrapper<>();
        query.eq(OrderEntity::getUserId, user.getId());
        query.ge(OrderEntity::getCreateDate, user.getActiveTeamBegin());
        query.lt(OrderEntity::getCreateDate, user.getActiveTeamEnd());
        Integer orderCount = orderDao.selectCount(query);
        //根据日期查询总金额
        LambdaQueryWrapper<RecordEntity> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordEntity::getUserId, user.getId());
        queryWrapper.eq(RecordEntity::getType, 1); //充值流水
        queryWrapper.ge(RecordEntity::getCreateDate, user.getActiveTeamBegin());
        queryWrapper.lt(RecordEntity::getCreateDate, user.getActiveTeamEnd());
        List<RecordEntity> recordEntities = recordDao.selectList(queryWrapper);
        Double orderMoney = recordEntities.stream().mapToDouble(a -> a.getAmount().doubleValue()).sum();
        //查询日期内交易金额

        String team1 = sysConfigService.getValue("alloy:team:level:count:1");
        if (orderCount >= Integer.parseInt(team1.split("_")[0]) && orderMoney > Double.parseDouble(team1.split("_")[1])) {
            user.setTeamLevel(1);
            user.setTeamName("合金初创者");
        }
        // 合金中创者：月单数要求三级内50单（大于等于）同时充值流水要求达50000元，领取月总充值的百分之10，连续3个月完成领取季度充值奖励总额的百分之12，连续6个月完成领取半年度充值奖励总额的百分之15，连续10-12个月完成领取年度充值奖励总额的百分之18，并邀请参加合金工业年度领导人峰会。
        String team2 = sysConfigService.getValue("alloy:team:level:count:2");
        if (orderCount >= Integer.parseInt(team2.split("_")[0]) && orderMoney > Double.parseDouble(team2.split("_")[1])) {
            if (null != user.getTeamLevel() && user.getTeamLevel() < 2) {
                user.setTeamLevel(2);
                user.setTeamName("合金中创者");
            }
        }
        //** 合金顶创者：月单数要求三级内300单（大于等于）同时充值流水要求达300000元，领取总充值的百分之15，连续3个月完成领取季度充值奖励总额的百分之18，连续6个月完成领取半年度充值奖励总额的百分之20，连续10-12个月完成领取年度充值奖励总额的百分之22，赠送宝马5系轿车一辆价值40万元，并邀请参加合金工业年度领导人峰会。
        String team3 = sysConfigService.getValue("alloy:team:level:count:3");
        if (orderCount >= Integer.parseInt(team3.split("_")[0]) && orderMoney > Double.parseDouble(team3.split("_")[1])) {
            if (null != user.getTeamLevel() && user.getTeamLevel() < 3) {
                user.setTeamLevel(3);
                user.setTeamName("合金顶创者");
            }
        }
        // 合金战略合伙人：月单数要求三级内1000（大于等于）同时充值流水要求达1000000元，领取总充值百分之20，连续3个月完成领取季度充值奖励总额的百分之22，连续6个月完成领取半年度充值奖励总额的百分之25，连续10-12个月完成领取年度充值奖励的百分之28，赠送奔驰S480轿车一辆价值150万，并邀请参加合金工业年度领导人峰会
        String team4 = sysConfigService.getValue("alloy:team:level:count:4");
        if (orderCount >= Integer.parseInt(team4.split("_")[0]) && orderMoney > Double.parseDouble(team4.split("_")[1])) {
            if (null != user.getTeamLevel() && user.getTeamLevel() < 4) {
                user.setTeamLevel(4);
                user.setTeamName("合金战略合伙人");
            }
        }

        userDao.updateById(user);

    }


    @Override
    public PageUtils buyRecords(RecordForm form, Integer userId) {
        form.setBeginIndex((form.getPage() - 1) * form.getLimit());

        QueryWrapper<OrderEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        queryWrapper.orderByDesc("create_date");
        Integer count = baseMapper.selectCount(queryWrapper);

        queryWrapper.last("limit " + form.getBeginIndex() + "," + form.getLimit());
        List<RecordVo> vos = new ArrayList<>();

        List<OrderEntity> orders = baseMapper.selectList(queryWrapper);
        if (!CollectionUtils.isEmpty(orders)) {
            for (OrderEntity entity : orders) {
                RecordVo vo = new RecordVo();
                vo.setType(entity.getType());
                vo.setTypeName(entity.getType().intValue() == 1 ? "CNY 订单" : "USDT 订单");
                vo.setProName(entity.getProName());
                vo.setAmountCny(entity.getAmountCny().setScale(2, RoundingMode.DOWN).stripTrailingZeros().toPlainString());
                vo.setAmountUsdt(entity.getAmountUsdt().setScale(2, RoundingMode.DOWN).stripTrailingZeros().toPlainString());
                vo.setStatus(1);
                vo.setTime(DateUtils.format(entity.getCreateDate(), DateUtils.DATE_TIME_PATTERN));
                vos.add(vo);
            }
        }
        return new PageUtils(vos, count, form.getLimit(), form.getPage());
    }

    private RecordEntity createRecord(OrderForm form, UserEntity user, ProductEntity product) {
        WalletTypeEnum buyType = WalletTypeEnum.get(form.getPayType());
        RecordEntity record = new RecordEntity();
        record.setUserId(user.getId());
        record.setMobile(user.getMobile());
        record.setType(OperateEnum.TYPE4.getType());
        record.setTypeName(OperateEnum.TYPE4.getMark());
        record.setRemark(buyType.getDesc() + "下单");
        if (WalletTypeEnum.CNY.equals(buyType)) {
            record.setAmount(product.getPriceCny());
        } else if (WalletTypeEnum.USDT.equals(buyType)) {
            record.setAmount(product.getPriceUsdt());
        }
        record.setFee(BigDecimal.ZERO);
        record.setStatus(1);
        record.setCreateDate(new Date());
        record.setUpdateDate(new Date());
        return record;
    }

    private OrderEntity createOrder(OrderForm form, UserEntity user, ProductEntity product) {
        WalletTypeEnum buyType = WalletTypeEnum.get(form.getPayType());
        OrderEntity order = new OrderEntity();
        order.setUserId(Servlets.getUserId());
        order.setMobile(user.getMobile());
        order.setType(form.getPayType());
        order.setProId(product.getId());
        order.setProName(product.getTitle());
        order.setPriceCny(product.getPriceCny());
        order.setPriceUsdt(product.getPriceUsdt());
        order.setQuantity(new BigDecimal(1));
        order.setAmountCny(product.getPriceCny());
        order.setAmountUsdt(product.getPriceUsdt());
        order.setRate(product.getRate());
        if (WalletTypeEnum.CNY.equals(buyType)) {
            order.setIncome(product.getPriceCny().multiply(product.getRate()));
            order.setTotalIncome(BigDecimal.ZERO);
            order.setLeftIncome(product.getPriceCny().multiply(product.getRate()).multiply(new BigDecimal(product.getTimes())));
        }

        if (WalletTypeEnum.USDT.equals(buyType)) {
            order.setIncome(product.getPriceUsdt().multiply(product.getRate()));
            order.setTotalIncome(BigDecimal.ZERO);
            order.setLeftIncome(product.getPriceUsdt().multiply(product.getRate()).multiply(new BigDecimal(product.getTimes())));
        }
        order.setTotalTimes(0);
        order.setLeftTimes(product.getTimes());
        order.setOrderNo(SnowFlakeUtil.nextId());
        order.setCreateDate(new Date());
        order.setUpdateDate(new Date());
        return order;
    }

}
